1
'*************************** Module Header ******************************'
2 ' Module Name: FTPFileSystem.vb
3 ' Project: VBFTPDownload
4 ' Copyright (c) Microsoft Corporation.
6 ' The class FTPFileSystem represents a file on the remote FTP server. When run
7 ' the FTP LIST protocol method to get a detailed listing of the files on an
8 ' FTP server, the server will response many records of information. Each record
9 ' represents a file. Depended on the FTP Directory Listing Style of the server,
13 ' 12-13-10 12:41PM <DIR> Folder A
15 ' 12-13-10 12:41PM [Size] File B
17 ' NOTE: The date segment is like "12-13-10" instead of "12-13-2010" if Four-digit
18 ' years is not checked in IIS.
22 ' drwxrwxrwx 1 owner group 0 Dec 1 12:00 Folder A
24 ' -rwxrwxrwx 1 owner group [Size] Dec 1 12:00 File B
26 ' NOTE: The date segment does not contains year.
29 ' This source is subject to the Microsoft Public License.
30 ' See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
31 ' All other rights reserved.
33 ' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
34 ' EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
35 ' WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
36 '*************************************************************************'
38 Imports System
.Text
.RegularExpressions
41 Public Class FTPFileSystem
43 Dim _originalRecordString
As String
46 ''' The original record string.
48 Public Property OriginalRecordString() As String
50 Return _originalRecordString
52 Set(ByVal value
As String)
53 _originalRecordString
= value
57 Dim _directoryListingStyle
As FTPDirectoryListingStyle
62 Public Property DirectoryListingStyle() As FTPDirectoryListingStyle
64 Return _directoryListingStyle
66 Set(ByVal value
As FTPDirectoryListingStyle
)
67 _directoryListingStyle
= value
76 Public Property Url() As Uri
80 Set(ByVal value
As Uri
)
88 ''' The name of this FTPFileSystem instance.
90 Public Property Name() As String
94 Set(ByVal value
As String)
99 Dim _isDirectory
As Boolean
102 ''' Specify whether this FTPFileSystem instance is a directory.
104 Public Property IsDirectory() As Boolean
108 Set(ByVal value
As Boolean)
113 Dim _modifiedTime
As Date
116 ''' The last modified time of this FTPFileSystem instance.
118 Public Property ModifiedTime() As Date
122 Set(ByVal value
As Date)
123 _modifiedTime
= value
130 ''' The size of this FTPFileSystem instance if it is not a directory.
132 Public Property Size() As Integer
136 Set(ByVal value
As Integer)
145 ''' Override the method ToString() to display a more friendly message.
147 Public Overrides
Function ToString() As String
148 Return String.Format("{0}" & vbTab
& "{1}" & vbTab
& vbTab
& "{2}", _
149 Me.ModifiedTime
.ToString("yyyy-MM-dd HH:mm"), _
150 If(Me.IsDirectory
, "<DIR>", Me.Size
.ToString()), Me.Name
)
154 ''' Find out the FTP Directory Listing Style from the recordString.
156 Public Shared
Function GetDirectoryListingStyle(ByVal recordString
As String) _
157 As FTPDirectoryListingStyle
158 Dim regex_Renamed
As Regex
= _
159 New System
.Text
.RegularExpressions
.Regex("^[d-]([r-][w-][x-]){3}$")
161 Dim header As String = recordString.Substring(0, 10)
163 ' If the style is UNIX, then the header is like "drwxrwxrwx
".
164 If regex_Renamed.IsMatch(header) Then
165 Return FTPDirectoryListingStyle.UNIX
167 Return FTPDirectoryListingStyle.MSDOS
172 ''' Get an FTPFileSystem from the recordString.
174 Public Shared Function ParseRecordString(ByVal baseUrl As Uri, _
175 ByVal recordString As String, _
176 ByVal type As FTPDirectoryListingStyle) _
178 Dim fileSystem As FTPFileSystem = Nothing
180 If type = FTPDirectoryListingStyle.UNIX Then
181 fileSystem = ParseUNIXRecordString(recordString)
183 fileSystem = ParseMSDOSRecordString(recordString)
186 ' Add "/" to the url if it is a directory
187 fileSystem.Url = New Uri(baseUrl, fileSystem.Name _
188 & (If(fileSystem.IsDirectory, "/", String.Empty)))
194 ''' The recordString is like
195 ''' Directory: drwxrwxrwx 1 owner group 0 Dec 13 11:25 Folder A
196 ''' File: -rwxrwxrwx 1 owner group 1024 Dec 13 11:25 File B
197 ''' NOTE: The date segment does not contains year.
199 Shared Function ParseUNIXRecordString(ByVal recordString As String) As FTPFileSystem
200 Dim fileSystem As New FTPFileSystem()
202 fileSystem.OriginalRecordString = recordString.Trim()
203 fileSystem.DirectoryListingStyle = FTPDirectoryListingStyle.UNIX
205 ' The segments is like "drwxrwxrwx
", "", "", "1", "owner
", "", "", "",
206 ' "group
", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
207 ' "0", "Dec
", "13", "11:25", "Folder
", "A
".
208 Dim segments() As String = fileSystem.OriginalRecordString.Split(" "c)
210 Dim index As Integer = 0
212 ' The permission segment is like "drwxrwxrwx
".
213 Dim permissionsegment As String = segments(index)
215 ' If the property start with 'd', then it means a directory.
216 fileSystem.IsDirectory = permissionsegment.Chars(0) = "d
"c
218 ' Skip the empty segments.
220 Do While segments(index) = String.Empty
224 ' Skip the directories segment.
226 ' Skip the empty segments.
228 Do While segments(index) = String.Empty
232 ' Skip the owner segment.
234 ' Skip the empty segments.
236 Do While segments(index) = String.Empty
240 ' Skip the group segment.
242 ' Skip the empty segments.
244 Do While segments(index) = String.Empty
248 ' If this fileSystem is a file, then the size is larger than 0.
249 fileSystem.Size = Integer.Parse(segments(index))
251 ' Skip the empty segments.
253 Do While segments(index) = String.Empty
258 Dim monthsegment As String = segments(index)
260 ' Skip the empty segments.
262 Do While segments(index) = String.Empty
267 Dim daysegment As String = segments(index)
269 ' Skip the empty segments.
271 Do While segments(index) = String.Empty
276 Dim timesegment As String = segments(index)
278 fileSystem.ModifiedTime = _
279 Date.Parse(String.Format("{0} {1} {2} ", _
280 timesegment, monthsegment, daysegment))
282 ' Skip the empty segments.
284 Do While segments(index) = String.Empty
288 ' Calculate the index of the file name part in the original string.
289 Dim filenameIndex As Integer = 0
291 For i As Integer = 0 To index - 1
292 ' "" represents ' ' in the original string.
293 If segments(i) = String.Empty Then
296 filenameIndex += segments(i).Length + 1
299 ' The file name may include many segments because the name can contain ' '.
300 fileSystem.Name = fileSystem.OriginalRecordString.Substring(filenameIndex).Trim()
306 ''' 12-13-10 12:41PM <DIR> Folder A
308 ''' <param name="recordString
"></param>
309 ''' <returns></returns>
310 Shared Function ParseMSDOSRecordString(ByVal recordString As String) _
312 Dim fileSystem As New FTPFileSystem()
314 fileSystem.OriginalRecordString = recordString.Trim()
315 fileSystem.DirectoryListingStyle = FTPDirectoryListingStyle.MSDOS
317 ' The segments is like "12-13-10", "", "12:41PM
", "", "","", "",
318 ' "", "", "<DIR
>", "", "", "", "", "", "", "", "", "", "Folder
", "A
".
319 Dim segments() As String = fileSystem.OriginalRecordString.Split(" "c)
321 Dim index As Integer = 0
323 ' The date segment is like "12-13-10" instead of "12-13-2010" if Four-digit years
324 ' is not checked in IIS.
325 Dim dateSegment As String = segments(index)
326 Dim dateSegments() As String = _
327 dateSegment.Split(New Char() {"-"c}, StringSplitOptions.RemoveEmptyEntries)
329 Dim month As Integer = Integer.Parse(dateSegments(0))
330 Dim day As Integer = Integer.Parse(dateSegments(1))
331 Dim year As Integer = Integer.Parse(dateSegments(2))
333 ' If year >=50 and year <100, then it means the year 19**
334 If year >= 50 AndAlso year < 100 Then
337 ' If year <50, then it means the year 20**
338 ElseIf year < 50 Then
342 ' Skip the empty segments.
344 Do While segments(index) = String.Empty
349 Dim timesegment As String = segments(index)
351 fileSystem.ModifiedTime = _
352 Date.Parse(String.Format("{0}-{1}-{2} {3}", year, month, day, timesegment))
354 ' Skip the empty segments.
356 Do While segments(index) = String.Empty
360 ' The size or directory segment.
361 ' If this segment is "<DIR
>", then it means a directory, else it means the
363 Dim sizeOrDirSegment As String = segments(index)
365 fileSystem.IsDirectory = _
366 sizeOrDirSegment.Equals("<DIR
>", StringComparison.OrdinalIgnoreCase)
368 ' If this fileSystem is a file, then the size is larger than 0.
369 If Not fileSystem.IsDirectory Then
370 fileSystem.Size = Integer.Parse(sizeOrDirSegment)
373 ' Skip the empty segments.
375 Do While segments(index) = String.Empty
379 ' Calculate the index of the file name part in the original string.
380 Dim filenameIndex As Integer = 0
382 For i As Integer = 0 To index - 1
383 ' "" represents ' ' in the original string.
384 If segments(i) = String.Empty Then
387 filenameIndex += segments(i).Length + 1
390 ' The file name may include many segments because the name can contain ' '.
391 fileSystem.Name = fileSystem.OriginalRecordString.Substring(filenameIndex).Trim()